﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using RpgLibrary.SpriteClasses;

namespace XRpgLibrary.SpriteClasses
{
    public enum AnimationKey 
    { 
        South, 
        West, 
        East, 
        North 
    }
    
    public class Animation
    {
        #region Field Region
        
        Rectangle[] frames;
        int framesPerSecond;
        TimeSpan frameLength;
        TimeSpan frameTimer;
        int currentFrame;
        int frameWidth;
        int frameHeight;
        
        #endregion

        #region Property Region
        
        public int FramesPerSecond
        {
            get { return framesPerSecond; }
            
            set
            {
                
                if (value < 1)
                    framesPerSecond = 1;
                else if (value > 60)
                    framesPerSecond = 60;
                else
                    framesPerSecond = value;

                frameLength = TimeSpan.FromSeconds(1 / (double)framesPerSecond);
            }
        }

        public Rectangle CurrentFrameRect
        {
            get { return frames[currentFrame]; }
        }
        
        public int CurrentFrame
        {
            get { return currentFrame; }
            set
            {
                currentFrame = (int)MathHelper.Clamp(value, 0, frames.Length - 1);
            }
        }
        public int FrameWidth
        {
            get { return frameWidth; }
        }
        
        public int FrameHeight
        {
            get { return frameHeight; }
        }
        #endregion

        #region Constructor Region

        public Animation(AnimationData data)
        {
            frames = data.Frames;
            this.frameWidth = frames[0].Width;
            this.frameHeight = frames[0].Height;
            this.FramesPerSecond = data.FramesPerSecond;
            Reset();
        }
        

        public Animation(int frameCount, int frameWidth, int frameHeight, int xOffset, int yOffset)
        {
            frames = new Rectangle[frameCount];
            this.frameWidth = frameWidth;
            this.frameHeight = frameHeight;
            for (int i = 0; i < frameCount; i++)
            {
                frames[i] = new Rectangle(
                    xOffset + (frameWidth * i),
                    yOffset,
                    frameWidth,
                    frameHeight);
            }

            FramesPerSecond = 24;
            Reset();
        }

        private Animation(Animation animation)
        {
            this.frames = animation.frames;
            FramesPerSecond = 24;
        }

        #endregion

        #region Method Region
        
        public void Update(GameTime gameTime)
        {
            frameTimer += gameTime.ElapsedGameTime;
            if (frameTimer >= frameLength)
            {
                frameTimer = TimeSpan.Zero;
                currentFrame = (currentFrame + 1) % frames.Length;
            }
        }

        public void Reset()
        {
            currentFrame = 0;
            frameTimer = TimeSpan.Zero;
        }

        #endregion

        #region Interface Method Region
        
        public object Clone()
        {
            Animation animationClone = new Animation(this);
            animationClone.frameWidth = this.frameWidth;
            animationClone.frameHeight = this.frameHeight;
            animationClone.Reset();
            
            return animationClone;
        }
        #endregion

        internal static Animation FromAnimationData(AnimationData animationData)
        {
            return new Animation(animationData);
        }

        internal AnimationData GetDataObject()
        {
            return new AnimationData(
                frames.Length,
                frames[0].Width,
                frames[0].Height,
                frames[0].X,
                frames[0].Y);
        }
    }
}
